#include <stdio.h>
#include <w32api.h>

#define WINVER WindowsXP
#include <winsock2.h>
#include <ws2tcpip.h>

static void usage(void);
static int scanPort(const char *node); 
static int scanPortForIPv4(const struct sockaddr_in *sockaddrIPv4);

static void usage(void)
{
    printf("BrickRed Studio Net Tools Port Scan Util, Made by Kaien Version 0.01\n");
    printf("usage:kportscan <host_name>\n");
}

int main(int argc, char *argv[])
{
    WSADATA wsaData;

    setvbuf(stdout, 0, _IONBF, 0);

    if (argc - 1 < 1)
    {
        usage();
        exit(EXIT_FAILURE);
    }

    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        fprintf(stderr, "WSAStartup failed\n");
        exit(EXIT_FAILURE);
    }
    atexit((void (*)(void))(WSACleanup));

    if (scanPort(argv[1]) != 0)
    {
        exit(EXIT_FAILURE);
    }

    return 0;
}

static int scanPort(const char *node)
{
    struct addrinfo *result = NULL;
    struct addrinfo *ptr = NULL;
    int err = 0;

    if ((err = getaddrinfo(node, NULL, NULL, &result)) != 0)
    {
        fprintf(stderr, "%s\n", gai_strerror(err));
        return -1;
    }

    for (ptr = result; ptr != NULL; ptr = ptr->ai_next)
    {
        switch(ptr->ai_family)
        {
        case AF_UNSPEC:
            printf("[Unspecified]\n");
            break;

        case AF_INET:
            if (scanPortForIPv4((struct sockaddr_in *)ptr->ai_addr) != 0)
            {
                return -1;
            }
            break;

        case AF_INET6:
            printf("[IPv6]\n");
            break;

        case AF_NETBIOS:
            printf("[NetBIOS]\n");
            break;
        }
    }

    freeaddrinfo(result);

    return 0;
}

static int scanPortForIPv4(const struct sockaddr_in *sockaddrIPv4)
{
    struct sockaddr_in saddr;
    SOCKET sock;

    memcpy(&saddr, sockaddrIPv4, sizeof(saddr));

    printf("[IPv4]%s\n", inet_ntoa(saddr.sin_addr));
    printf("    [TCP Port Scan]\n");

    for (int i = 80; i <= 80; ++i)
    {
        saddr.sin_port = htons(i);
        sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (INVALID_SOCKET == sock)
        {
            fprintf(stderr, "open socket failed\n");
            return -1;
        }

        if (connect(sock, (struct sockaddr *)&saddr,
                    sizeof(struct sockaddr)) == 0)
        {
            printf("        port[%d] open\n", i);
        }
        closesocket(sock);
    }

    return 0;
}
